package roots;

/**
 * Die class is geskryf met die doel om verskillende algoritmes te vergelyk wat wortels kan bepaal.
 * <p>
 * Op die oomblik is daar net 2 verskillende algoritmes, Calculator(), en Newton(). Ek mik daarna om nog
 * verskillende maniere by te sit.
 * <p>
 * My programmeering styl is dalk frustreerend om te volg of kan dalk op baie verskillende maniere 
 * verbeter, as iemand enige verbeteringe of voorstelle het, dit sal altyd welkom wees.
 * 
 * 	@author Coenie
 *	Feb 14, 2009
 * 	roots
 * @version 2
 */

public class Roots {

	/**
	 * Stel dit om meer informasie te vertoon in die Console.
	 */
	static boolean debug = false; 


	/**
	 * Dit is die getal wat se wortel bepaal moet word.
	 */
	static double a = 16;

	/**
	 * Dit stel die hoeveelste wortel wat uitgewerk moet word (x^n - a = 0).
	 */
	static double n = 2;

	/**
	 * Dit is die verskill tussen opeenvolgende waardes van die wortel en bepaal hoe akuraat die benadering moet wees.
	 */
	static double diff = 0.00001;

	static int i = 0;
	static double x1 = a/n;	
	static double x2 = 0;

	/**
	 * Roep methods newton() en calculator().
	 * 
	 * @param args String
	 */
	public static void main(String[] args) {

		newton();

		calculator();

	}

	/**
	 * Ontvang 'n String en print dit uit as debug true is.
	 * 
	 * @param s String
	 */
	public static void print(String s){

		if(debug == true){

			System.out.println(s);
		}
	}

	/**
	 * Ontvang 'n double en print dit uit as debug true is.
	 * 
	 * @param d double
	 */
	public static void print(double d){

		if(debug == true){

			System.out.println("" + d);
		}
	}

	/**
	 * Werk die positiewe verskil tussen a en b uit.
	 * 
	 * @param a double
	 * @param b double
	 * @return double
	 */
	public static double diff(double a, double b){

		return Math.abs(a - b);
	}

	/**
	 * Print 'n klomp '-' uit  as debug true is.
	 */
	public static void line(){

		if(debug == true){
			System.out.println("----------------------------------------");
		}
	}

	/**
	 * Word gebruik om i, x1 en x2 terug na die oorspronklikke waardes toe terug te stel sodat
	 * die volgende wortel algoritme getoets kan word.
	 */
	public static void reset(){

		i = 0;
		x1 = a/n;
		x2 = 0;
	}

	/**
	 * Hierdie is die standaard newton algoritme om 'n wortel te bepaal.
	 * <p>   
	 * {@link <a href="http://en.wikipedia.org/wiki/Newton's_method">Die</a>}
	 * algoritme konvergeer vinnig met vergelyking tot bv. die calculator algoritme.  
	 */
	public static void newton(){

		while(true){

			x2 = x1 - (Math.pow(x1, n) - a)/(n*(Math.pow(x1, n - 1)));
			i++;
			print(i);
			print(x1);

			if(diff(x1, x2) < diff){

				break;
			}

			x1 = x2;
		}
		line();
		System.out.println("[Newton]Root: " + x1 + "\nIterations: " + i);
		line();	
		reset(); 
	}
	/**
	 * Hierdie is (blykbaar) die algoritme wat 'n sakrekenaar gebruik om 'n wortel te bepaal.
	 * <p>
	 * {@link <a href="http://richardbowles.tripod.com/javascript/assignments/assign1.htm">Die</a>}
	 *  algoritme kovergeer uiters stadig in vergelyking met die newton algoritme.
	 * Nog 'n nadeel is dat die formule verander afhangende van die hoeveelste wortel wat mens wil uitwerk.
	 */
	public static void calculator(){

		while(true){

			x2 = (a - 1)/(x1 + 1) + 1;
			i++;
			print(i);
			print(x1);

			if(diff(x1, x2) < diff){

				break;
			}

			x1 = x2;
		}
		line();
		System.out.println("[Calculator]Root: " + x1 + "\nIterations: " + i);
		line();
		reset();
	}


}
